import struct
import ctypes
import codecs
import tkinter as tk
import tkinter.filedialog
import tkinter.messagebox
import re
import os
import traceback
from lupa import LuaRuntime
import threading

def float_to_hex(f):
    return hex(struct.unpack('<I', struct.pack('<f', f))[0])
def float2hex(s):
    fp = ctypes.pointer(ctypes.c_float(s))
    cp = ctypes.cast(fp,ctypes.POINTER(ctypes.c_long))
    return hex(cp.contents.value)
def hex_to_float(h):
    i = int(h,16)
    return struct.unpack('<f',struct.pack('<I', i))[0]
def hex2float(h):
    i = int(h,16)
    cp = ctypes.pointer(ctypes.c_int(i))
    fp = ctypes.cast(cp,ctypes.POINTER(ctypes.c_float))
    return fp.contents.value
'''
def doo2list(_doo_IO):
    f = open(_doo_IO, 'rb')
    f.seek(16)
    s = f.read(1)
    wb = []
    strdate = []
    ai = ""
    while s:
            byte = ord(s)
            wb.append(str('%02X'%(byte)))
            s = f.read(1)
    r = ""
    for i in range(len(wb)):
        v = chr(int(wb[i],16))
        if bool(re.search('[a-zA-Z]',v)):
            r += v
        elif wb[i] == "FF":
            r += "F"
        elif wb[i] == "00":
            r += "0"
        else:
            r += "."
    print("1")
    for i in range(int(len(wb)/111)):
        #player 玩家12为NA  玩家13为 NV  玩家14位NE  玩家15为NP
        UntsStr = ""
        ai += wb[i*111+37]
        if int(ai,16) <= 9:
            strdate.append('0')
            strdate.append(str(int(ai,16)))
        else:
            if int(ai,16) < 12:
                strdate.append(str(int(ai,16))[0])
                strdate.append(str(int(ai,16))[1])
            else:
                if int(ai,16) == 12:
                    strdate.append('N')
                    strdate.append('A')
                else:
                    if int(ai,16) == 13:
                        strdate.append('N')
                        strdate.append('V')
                    else:
                        if int(ai,16) == 14:
                            strdate.append('N')
                            strdate.append('E')
                        else:
                            if int(ai,16) == 15:
                                strdate.append('N')
                                strdate.append('P')
        ai = ""
        #units
        ai += wb[i*111]
        ai += wb[i*111+1]
        ai += wb[i*111+2]
        ai += wb[i*111+3]
        UntsStr = I2S(int(ai,16))
        strdate.append(I2S((int(ai,16))))
        ai = ""
        #X
        ai += wb[i*111+11]
        ai += wb[i*111+10]
        ai += wb[i*111+9]
        ai += wb[i*111+8]
        floot = 0.00
        floot = hex_to_float(ai)
        if floot < 0:
            floot -= 0.001
        else:
            floot += 0.001
        strdate.append(str(floot).split(".")[0] + "." + str(floot).split(".")[1][0:2])
        ai =""
        #Y
        ai += wb[i*111+15]
        ai += wb[i*111+14]
        ai += wb[i*111+13]
        ai += wb[i*111+12]
        floot = 0.00
        floot = hex_to_float(ai)
        if floot < 0:
            floot -= 0.001
        else:
            floot += 0.001
        strdate.append(str(floot).split(".")[0] + "." + str(floot).split(".")[1][0:2])
        ai =""
        #R
        ai += wb[i*111+23]
        ai += wb[i*111+22]
        ai += wb[i*111+21]
        ai += wb[i*111+20]
        floot = 0.00
        floot = hex_to_float(ai) * 180 / 3.14
        if floot < 0:
            floot -= 0.001
        else:
            floot += 0.001
        strdate.append(str(floot).split(".")[0] + "." + str(floot).split(".")[1][0:2])
        ai =""
        if UntsStr == "sloc":
            strdate.pop()
            strdate.pop()
            strdate.pop()
            strdate.pop()
            strdate.pop()
            strdate.pop()
    f.close()
    return strdate
'''
class Executor(threading.Thread):
    """
        执行lua的线程类
    """
    lock = threading.RLock()
    luaScriptContent = None
    luaRuntime = None
 
    def __init__(self,api,params):
        threading.Thread.__init__(self)
        self.params = params
        self.api = api
 
    def run(self):
        # 执行具体的函数,返回结果打印在屏幕上
        luaRuntime = self.getLuaRuntime()
        rel = luaRuntime(self.api, self.params)
        for i in range(1,len(rel)+1):
            '''
            rel[i]['玩家']
            rel[i]['ID']
            rel[i]['位置'][1]
            rel[i]['位置'][
            rel[i]['角度']
            '''
            #player
            if rel[i]['ID'] == 'sloc':
                continue
            if rel[i]['玩家'] < 10:
                doo.append('0')
                doo.append(str(rel[i]['玩家']))
            elif rel[i]['玩家'] < 12:
                doo.append(str(rel[i]['玩家'])[0])
                doo.append(str(rel[i]['玩家'])[1])
            elif rel[i]['玩家'] == 12:
                doo.append('N')
                doo.append('A')
            elif rel[i]['玩家'] == 13:
                doo.append('N')
                doo.append('V')
            elif rel[i]['玩家'] == 14:
                doo.append('N')
                doo.append('E')
            elif rel[i]['玩家'] == 15:
                doo.append('N')
                doo.append('P')
            #ID
            doo.append(rel[i]['ID'])
            #X
            doo.append(str(round(rel[i]['位置'][1],2)))
            #Y
            doo.append(str(round(rel[i]['位置'][2],2)))
            #R
            doo.append(str(round(rel[i]['角度'],2)))

    def getLuaRuntime(self):
        """
            从文件中加载要执行的lua脚本,初始化lua执行环境
        """
 
        # 上锁,保证多个线程加载不会冲突
        if Executor.lock.acquire():
            if Executor.luaRuntime is None:
                fileHandler = open('./war3mapUnits_doo.lua',encoding='UTF-8')
                content = ''
                content = fileHandler.read()
                # 创建lua执行环境
                Executor.luaScriptContent = content
                luaRuntime = LuaRuntime()
                luaRuntime.execute(content)
 
                # 从lua执行环境中取出全局函数functionCall作为入口函数调用,实现lua的反射调用
                g = luaRuntime.globals()
                function_call = g.functionCall
                Executor.luaRuntime = function_call
            Executor.lock.release()
 
        return Executor.luaRuntime


def doo2list(filename):
    global doo
    doo = []
    executor1 = Executor('test3',filename)
    executor1.start()
    executor1.join()
    return doo


def S2B(_str):
    li=[]
    for i in range(len(_str)):
        li.append(bytes.fromhex(str('%02X'%(ord(_str[i])))))
    return li
def I2S(x):
    a=x//16777216
    b=(x%16777216)//65536
    c=(x%65536)//256
    d=x%256
    return chr(a) + chr(b) + chr(c) + chr(d) 
def listcompare(_list0,_list1):
    for i in range(len(_list0)):
        if _list0[i] != _list1[i]:
            return False
    return True
def GetbyteslistStrid(_list,we,_number):
    _list1 = []
    for i in range(len(_list)):
        if _list[i] == we[0]:
            if listcompare(_list[i:(i+len(we))],we):
                _list1.append(i)
    if len(_list1) > 1:
        return _list1[_number]
    else:
        return _list1[0]
def main(_doo_IO,_wtg_IO,_str):
    ll = doo2list(_doo_IO)
    fi = _wtg_IO
    readstr = fi.read(1)
    wb = []
    numlist = []
    we = [b'\x00',b'\x00',b'\x00',b'\x00',b'\x00',b'\x02',b'\x00',b'\x00',b'\x00']
    wei = S2B(_str)
    test = "" # TEST
    while readstr:
        byte = readstr
        byte = bytes.fromhex(str('%02X'%(ord(byte))))
        test += chr(ord(byte))
        wb.append(byte) 
        readstr = fi.read(1)
    if ord(wb[8]) < 2:
        numlist.append(GetbyteslistStrid((wb),we,0) + 5) #变更类别声明结束符
        numlist.append(GetbyteslistStrid((wb),we,0) + 9) #插入新类别
    elif ord(wb[8]) >= 2:
        numlist.append(GetbyteslistStrid((wb),we,1) + 5) #变更类别声明结束符
        numlist.append(GetbyteslistStrid((wb),we,1) + 9) #插入新类别
    numlist.append(GetbyteslistStrid((wb),wei,0) - 4) #记录触发个数
    print(hex(numlist[0]))
    print(hex(numlist[1]))
    print(hex(numlist[2]))

    wb[numlist[0]] = struct.pack('B',ord(wb[8]))
    wb[8] = struct.pack('B',ord(wb[8]) + 1)
    wb[numlist[2]] = struct.pack('B',ord(wb[numlist[2]]) + 1)
    wi = S2B("Unit_New")
    wi.append(b'\x00\x00\x00\x00\x00\x02\x00\x00\x00')
    wi.reverse()
    for op in range(len(wi)):
        wb.insert(numlist[1],wi[op])
    
    s = []
    s += S2B("Unit2")                   #ID
    s.append(b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
    s.append(struct.pack('B',ord(wb[8]) - 1))
    s.append(b'\x00\x00\x00')
    numtrigger = int(len(ll) /6 + 1) #触发个数+1
    if numtrigger >= 255:
        s.append(struct.pack('B',numtrigger % 256))#动作个数
        s.append(struct.pack('B',int(numtrigger / 256)))#动作个数 256进1
        s.append(b'\x00\x00')
    else:
        s.append(struct.pack('B',numtrigger))#动作个数
        s.append(b'\x00\x00\x00')
    s.append(b'\x02\x00\x00\x00\x20') #触发声明
    num1 = int(len(ll)/6)
    for i in range(int(len(ll)/6)):
        s.append(b'\x43\x72\x65\x61\x74\x65\x55\x6E\x69\x74') #CreateUnit函数
        s.append(b'\x00\x01\x00\x00\x00\x00\x00\x00\x00') #函数头
        s.append(b'\x50\x6C\x61\x79\x65\x72') #player参数
        s += S2B(ll[i*6])
        s += S2B(ll[i*6+1])
        s.append(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00') #数值参数尾
        s += S2B(ll[i*6+2])
        s.append(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00') #数值参数尾
        s += S2B(ll[i*6+3])
        s.append(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00') #数值参数尾
        s += S2B(ll[i*6+4])
        s.append(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00') #数值参数尾
        s += S2B(ll[i*6+5])
        s.append(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') #预设参数尾
        if num1 != 1:
            s.append(b'\x02\x00\x00\x00\x20') #函数结尾
        else:
            s.append(b'\x00\x00\x00\x00') #动作结尾
        num1 -= 1
    s.append(b'\x4D\x61\x70\x49\x6E\x69\x74\x69\x61\x6C\x69\x7A\x61\x74\x69\x6F\x6E\x45\x76\x65\x6E\x74') #地图初始化事件
    s.append(b'\x00\x01\x00\x00\x00\x00\x00\x00\x00') #触发结尾
    wb += s
    return wb
def UI():
    file_path = tkinter.filedialog.askopenfilename(title=u'选择doo', filetypes=[(".doo", ".doo"),('All Files', ' *')])
    if file_path == "":
        return
    file_path1 = tkinter.filedialog.askopenfilename(title=u'选择wtg', filetypes=[(".wtg", ".wtg"),('All Files', ' *')]) 
    if file_path1 == "":
        return
    file_path2 = tkinter.filedialog.asksaveasfilename(title=u'保存wtg', filetypes=[(".wtg", ".wtg"),('All Files', ' *')],defaultextension=".wtg")
    if file_path2 == "":
        return
    fi = open(file_path1, 'rb')
    fe = open(file_path2, 'wb')
    fe.writelines(main(file_path,fi,str(L2.get())))
    fi.close()
    fe.close()
    ERRORUI()
    return
def ERRORUI():
        tk.messagebox.showinfo( "提示" ,"添加成功")

root = tk.Tk()
w = tk.Label(root, text="本软件将单位在WE中的放置情况(war3mapUnits.doo)以触发的形式添加到.wtg(触发编辑器内容)文件里面\n注：记得备份\nby然然是bake\n多谢冰火妹妹lua的技术支持")
wi = tk.Button(root, text="打开文件", command=UI)
L1 = tk.Label(root, text="输入你的第一个触发名称(不能为中文")
L2 = tk.Entry(root)
L1.pack()
L2.pack()
w.pack()
wi.pack()
root.mainloop()
